import json
import re
import uuid
from apps.rbac import models as db_rabc
from django.views import View
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.backends import ModelBackend
from apps.rbac import models as rbac_db
from apps.cmdb import models as asset_db
from apps.logs import models as log_db
from plugins.public import encryption,perms_control


class CustomBackend(ModelBackend):
    """自定义登录认证"""
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = rbac_db.User.objects.get(username=username)
            if user:
                str_key = db_rabc.Dict.objects.get(dict_key="ENCRYPT_KEY").dict_val
                pc = encryption.prpcrypt(str_key)  # 初始化密钥
                aes_passwd = pc.encrypt(password)
                user_passwd = user.password.strip("b").strip("'").encode(encoding="utf-8")
                if aes_passwd == user_passwd:
                    return user
        except Exception as e:
            print(e)
            return None

def login_check(func):
    """登录认证装饰器"""
    def wrapper(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("username"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return wrapper


def perms_check(func):
    """权限装饰器"""
    def wrapper(request, *args, **kwargs):
        try:
            req_url = request.get_full_path()
            try:
                paths=req_url.strip().strip("/").split("/")[:2]
                try:
                    ck = int(paths[1])
                    req_url = "/{}/".format(paths[0])
                except:
                    req_url = "/{}/{}/".format(paths[0],paths[1])
            except:
                paths =req_url.strip().strip("/").split("/")
                req_url = "/{}/".format(paths[0])

            req_method = request.method
            if req_method == "GET":
                req_data = None
            elif req_method == "POST":
                req_data = {}
                for i in request.POST:
                    req_data[i] =  request.POST.get(i)
                try:
                    req_data.pop('csrfmiddlewaretoken')
                except Exception as e:
                    print(e)
            else:
                req_data = request.body.decode()

            uuid_str = "{}{}".format(req_url, req_method)
            perms_key = str(uuid.uuid3(uuid.NAMESPACE_DNS, uuid_str))
            try:
                perms_obj = rbac_db.Permission.objects.get(perms_id=perms_key)
                action = perms_obj.title
                perms_menu = perms_obj.parent.title
                perms_list = request.session['perms_list']
                if perms_key in perms_list:
                    status = "SUCCESS"
                    if req_data:
                        log_obj=log_db.UserLog(user=request.session['username'], action=action,menu=perms_menu,status=status, req_data=req_data)
                        log_obj.save()
                    return func(request, *args, **kwargs)
                else:
                    status = "DENY"
                    if req_data:
                        log_obj = log_db.UserLog(user=request.session['username'], action=action, menu=perms_menu,
                                                  status=status, req_data=req_data)
                        log_obj.save()
                    ret = {"status": "False", "info": "权限不足，请联系管理员"}
                    data = json.dumps(ret,ensure_ascii=False)
                    return HttpResponse(data)
            except Exception as E:
                print(E)
                ret = {"status": "False", "info": "出现严重错误，请检查日志"}
                data = json.dumps(ret, ensure_ascii=False)
                return HttpResponse(data)
        except Exception as e:
            ret = {"status": "False", "info": e}
            data = json.dumps(ret, ensure_ascii=False)
            return HttpResponse(data)
    return wrapper



class LoginView(View):
    """登录视图"""
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        """
        处理GET请求
        """
        return render(request, 'base/login.html')

    def post(self, request):
        """
        处理POST请求
        """
        username = request.POST.get('username')
        passwd = request.POST.get('passwd')

        user = authenticate(username=username, password=passwd)

        if user:
            login(request, user)
            #设置会话参数
            request.session['username'] = user.username
            request.session['is_superuser'] = user.is_superuser
            request.session['role_id'] = user.role_id
            #更新用户状态
            user.is_online = "online"
            user.save()

            #获取用户权限清单
            request.session['menu_list'] = perms_control.menus_list(username)
            request.session['perms_list'] = perms_control.perms_list(username)


            next_url = request.POST.get("next")
            if next_url:
                return redirect(next_url)
            else:
                return redirect('/')
        else:
            return render(request, 'base/login.html', {"msg": "用户名或密码错误,请重新登录！"})

@login_check
def Logout(request):
    """退出登陆"""
    username = request.session['username']
    user_obj = rbac_db.User.objects.get(username=username)
    user_obj.is_online = "offline"
    user_obj.save()
    logout(request)
    request.session.delete()
    return render(request, "base/login.html")

@login_check
@perms_check
def change_passwd(request):
    """修改用户密码"""
    new_passwd = request.POST.get("new_passwd")
    user_id = request.POST.get("user_id")
    user_self = request.POST.get("user_self")
    if user_self:
        user_name = request.session['user_name']
        user_obj = db_rabc.User.objects.get(user_name=user_name)
    else:
        user_obj = db_rabc.User.objects.get(id=user_id)
    # 加密密码
    str_key = db_rabc.Dict.objects.get(dict_key="ENCRYPT_KEY").dict_val
    pc = encryption.prpcrypt(str_key)  # 初始化密钥
    aes_passwd = pc.encrypt(new_passwd)
    user_obj.password = aes_passwd
    user_obj.save()
    ret = {"status": "True", "info": "修改成功"}
    data = json.dumps(ret)
    return HttpResponse(data)



@login_check
def add_lg_user(request):
    user_id = request.POST.get("user_id")
    login_user = request.POST.get("login_user")
    login_passwd = request.POST.get("login_passwd")
    login_id_rsa = request.POST.get("login_id_rsa")
    id_rsa_pwd = request.POST.get("id_rsa_pwd")
    lg_id = request.POST.get("lg_id")
    action = request.POST.get("action")
    str_key = db_rabc.Dict.objects.get(dict_key="ENCRYPT_KEY").dict_val
    pc = encryption.prpcrypt(str_key)  # 初始化密钥
    if action:
        # 加密密码
        if login_passwd:
            login_passwd = pc.encrypt(login_passwd)
        if id_rsa_pwd:
            id_rsa_pwd = pc.encrypt(id_rsa_pwd)
        if int(lg_id) ==0:
            lg_obj = db_rabc.LoginAccount(user_id=user_id,login_user=login_user,login_passwd=login_passwd,login_id_rsa=login_id_rsa,id_rsa_pwd=id_rsa_pwd)
            lg_obj.save()
            ret = {"status": "True", "info": "添加成功"}
        else:
            lg_obj = db_rabc.LoginAccount.objects.get(id=lg_id)
            lg_obj.login_user=login_user
            lg_obj.login_passwd=login_passwd
            lg_obj.login_id_rsa=login_id_rsa
            lg_obj.id_rsa_pwd=id_rsa_pwd
            lg_obj.save()
            ret = {"status": "True", "info": "修改成功"}
        data = json.dumps(ret)
        return HttpResponse(data)
    else:
        try:
            lg_obj = db_rabc.LoginAccount.objects.get(user_id=user_id)

            if lg_obj.login_passwd:
                login_passwd = pc.decrypt(lg_obj.login_passwd.strip("b").strip("'")).decode()
            if lg_obj.id_rsa_pwd:
                id_rsa_pwd = pc.decrypt(lg_obj.id_rsa_pwd.strip("b").strip("'")).decode()
            lg_obj = {"login_user":lg_obj.login_user,"login_passwd":login_passwd,"login_id_rsa":lg_obj.login_id_rsa,"id_rsa_pwd":id_rsa_pwd,"lg_id":lg_obj.id}
        except:
            lg_obj = {"lg_id":0}

        data = json.dumps(lg_obj)
        return HttpResponse(data)


@login_check
@perms_check
def get_role_perms(request):
    """获取角色权限"""
    role_id = request.POST.get("role_id")
    #获取角色已授权菜单
    menu_list = perms_control.get_perms_list(role_id)
    perms_list = perms_control.perms_id_list(role_id)
    #提取角色已有授权的菜单id
    one_menu_ids = []
    two_menu_ids = []
    menu_perms_ids = []
    for i in menu_list:
        one_menu_ids.append(i['id'])
        for j in i['two_menu']:
            two_menu_ids.append(j['id'])
            menu_perms = rbac_db.Permission.objects.filter(parent_id=j['id'])
            for k in menu_perms:
                if k.id in perms_list:
                    menu_perms_ids.append(k.id)

    #获取所有权限
    all_menu_list = []
    one_menu = rbac_db.Permission.objects.filter(perms_type__contains="一级菜单")
    for i in one_menu:
        two_menu = rbac_db.Permission.objects.filter(parent_id=i.id)
        two_menu_list = []
        for j in two_menu:
            menu_perms = rbac_db.Permission.objects.filter(parent_id=j.id)
            menu_perms_list = []
            for k in menu_perms:
                menu_perms_list.append({'id':k.id,'perms': k.title})
            two_menu_list.append({'id':j.id,'perms': j.title,"menu_perms":menu_perms_list})
        all_menu_list.append({'id':i.id,'perms': i.title, "two_menu": two_menu_list})

    #生成菜单树
    nodes = []
    for i in all_menu_list:
        if i["id"] in one_menu_ids:
            nodes.append({"id": i['id'], "pId":0, "name": i['perms'], 'open': True,'checked': True})
        else:
            nodes.append({"id": i['id'], "pId": 0, "name": i['perms'], 'open': True})
        for j in i['two_menu']:
            node_id ="{}#{}".format(i['id'],j['id'])
            if j['id'] in two_menu_ids:
                nodes.append({"id": node_id, "pId":i['id'] , "name": j['perms'], 'open': True, 'checked': True})
            else:
                nodes.append({"id": node_id, "pId": i['id'], "name": j['perms'], 'open': True})
            for  k in j["menu_perms"]:
                perms_node_id = "{}#{}#{}".format(i['id'], j['id'],k["id"])
                if k['id'] in menu_perms_ids:
                    nodes.append({"id": perms_node_id, "pId": node_id, "name": k['perms'], 'open': True, 'checked': True})
                else:
                    nodes.append({"id": perms_node_id, "pId": node_id, "name": k['perms'], 'open': True})

    ret = {"status": "True", "info":nodes}
    data = json.dumps(ret)
    return HttpResponse(data)


@login_check
@perms_check
def add_role_perms(request):
    """权限授权"""
    menu_nums = request.POST.get("node_id_json")
    role_id = request.POST.get("role_id")
    role_obj = rbac_db.Role.objects.get(id=role_id)
    menu_nums = json.loads(menu_nums)
    role_obj.permissions.clear()
    for i in menu_nums:
        i = str(i)
        if re.search(r"#",i):
            id = i.split("#")[-1]
        else:
            id= i
        menu_obj = rbac_db.Permission.objects.get(id=id)
        role_obj.permissions.add(menu_obj)
    data = "授权已更新，重新登录即生效！"
    ret = {"status": "True", "info": data}
    data = json.dumps(ret)
    return HttpResponse(data)


@login_check
@perms_check
def get_role_asset(request):
    """获取资产"""
    role_id = request.POST.get("role_id")
    role_obj = rbac_db.Role.objects.get(id=role_id)
    hostgroup_obj = asset_db.AssetGroup.objects.all()
    host_list = role_obj.asset.all()
    asset_num_list = []
    for i in host_list:
        host_num = str(i.asset_group_id) + "#" + str(role_id) + "#" + str(i.id)
        asset_num_list.append(host_num)

    nodes = []
    for i in hostgroup_obj:
        hostgroup_id = i.id
        hostgroup_name = i.group_name
        host_obj = asset_db.Asset.objects.filter(asset_group_id=hostgroup_id)
        if host_obj:
            nodes.append({"id": hostgroup_id, "pId": 0, "name": hostgroup_name, "open": "True",'checked': True})
            for j in host_obj:
                host_num = str(hostgroup_id) + "#" + str(role_id) + "#" + str(j.id)
                if host_num in asset_num_list:
                    nodes.append({"id": host_num, "pId": hostgroup_id, "name": j.admin_ip, 'open': True, 'checked': True})
                else:
                    nodes.append({"id": host_num, "pId": hostgroup_id, "name": j.admin_ip, 'open': True})
    ret = {"status": "True", "info": nodes}
    data = json.dumps(ret)
    return HttpResponse(data)


@login_check
@perms_check
def add_role_asset(request):
    """资产授权"""
    asset_nums = request.POST.get("node_id_json")
    role_id = request.POST.get("role_id")
    role_obj = rbac_db.Role.objects.get(id=role_id)
    asset_nums = json.loads(asset_nums)
    role_obj.asset.clear()
    for i in asset_nums:
        if re.search(r"#",str(i)):
            asset_id = i.split("#")[-1]
            host_obj = asset_db.Asset.objects.get(id=asset_id)
            role_obj.asset.add(host_obj)
    data = "资产授权成功"
    ret = {"status": "True", "info": data}
    data = json.dumps(ret)
    return HttpResponse(data)


@login_check
@perms_check
def get_role_platform(request):
    """获取角色平台信息"""
    role_id = request.POST.get("role_id")
    role_obj = rbac_db.Role.objects.get(id=role_id)
    project_obj = game_db.ProjectList.objects.all()
    platform_list = role_obj.platform.all()

    platform_num_list = []
    for i in platform_list:
        platform_num_list.append(i.id)

    nodes = []
    for i in project_obj:
        nodes.append({"id": i.id, "pId": -1, "name": i.project_name, "open": "True", 'checked': True})
        platform_obj = game_db.PlatformList.objects.filter(project_id=i.id)
        for j in platform_obj:
            platform_id =  str(i.id)+ "#" + str(j.id)
            platform_name = j.platform_name
            if j.id in platform_num_list:
                nodes.append({"id": platform_id, "pId": i.id, "name": platform_name, "open": "True",'checked': True})
            else:
                nodes.append({"id": platform_id, "pId": i.id, "name": platform_name, "open": "True",})

    ret = {"status": "True", "info": nodes}
    data = json.dumps(ret,indent=4)
    return HttpResponse(data)


@login_check
@perms_check
def add_role_platform(request):
    """资产授权"""
    platform_nums = request.POST.get("node_id_json")
    role_id = request.POST.get("role_id")
    role_obj = rbac_db.Role.objects.get(id=role_id)

    platform_nums = json.loads(platform_nums)
    role_obj.platform.clear()
    for i in platform_nums:
        if re.search(r"#",str(i)):
            id = i.split("#")[-1]
            platform_obj = game_db.PlatformList.objects.get(id=id)
            role_obj.platform.add(platform_obj.id)
    data = "授权成功"
    ret = {"status": "True", "info": data}
    data = json.dumps(ret)
    return HttpResponse(data)


